package com.futvan.z.framework.core;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.futvan.z.framework.common.bean.Code;
import com.futvan.z.framework.common.bean.Result;
import com.futvan.z.framework.util.DateUtil;
import com.futvan.z.framework.util.JsonUtil;
import com.futvan.z.framework.util.SpringUtil;
import com.futvan.z.framework.util.StringUtil;
import com.futvan.z.system.zmessages.ZmessagesService;
import com.futvan.z.system.zmessages.z_messages;
import com.futvan.z.system.zuser.z_user;
/**
 * WebSocket处理类
 * @author zz
 *
 */
public class WebSocketHandler extends TextWebSocketHandler{

	/**
	 * 接收信息
	 */
	@Override
	public void handleTextMessage(WebSocketSession session, TextMessage message)throws Exception{ 
		//消息参数转为z_messages对象
		z_messages msg = TextMessageToZMessage(message);
		//发送消息
		Result result = sendMessage(msg);
		//返回发送信息给发送人
		session.sendMessage(new TextMessage(JsonUtil.getJson(result).getBytes()));
	}

	/**
	 * 	系统发送广播【未写完】
	 * @param touserid
	 * @param msg_text
	 * @return
	 */
	public static Result sendMessage(String touserid,String msg_text) {

		z_messages msg = new z_messages();
		msg.setFromuserid("sa");
		msg.setFromusername(z.users.get("sa").getUser_name());
		msg.setTouserid(touserid);
		msg.setTousername(z.users.get(touserid).getUser_name());
		msg.setMsgtype("0");
		msg.setMsg(msg_text);


		return null;
	}

	/**
	 * 发送消息
	 * @param msg
	 * @return
	 * @throws Exception 
	 */
	public static Result sendMessage(z_messages msg) throws Exception {
		Result result =  new Result();
		if(z.isNotNull(msg)) {
			result.setData(msg);//设置消息对象
			if(z.isNotNull(msg.getCommand_type())) {
				if("usertouser".equals(msg.getCommand_type())) {
					//用户间通信
					SendMessage_usertouser(msg,result);
				}else if("user_on_line".equals(msg.getCommand_type())) {
					//用户上线
					SendMessage_user_on_line(msg,result);
				}else if("user_off_line".equals(msg.getCommand_type())) {
					//用户下线
					SendMessage_user_off_line(msg,result);
				}else if("system_message".equals(msg.getCommand_type())) {
					//系统通知
					SendMessage_system_message(msg,result);
				}else if("group_message".equals(msg.getCommand_type())) {
					//群发消息
					SendMessage_group_message(msg,result);
				}else if("e_message".equals(msg.getCommand_type())) {
					//异常信息发送
					SendMessage_e_message(msg,result);
				}else {
					result.setCode(Code.ERROR);
					result.setMsg("即时通讯错误|未知消息命令类型");
				}
			}else {
				result.setCode(Code.ERROR);
				result.setMsg("即时通讯错误|通信命令不能为空");
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("即时通讯错误|z_messages参数为空");
		}
		return result;
	}


	/**
	 * 发送异常信息到前台
	 * @param msg
	 * @param result
	 * @throws Exception
	 */
	private static void SendMessage_e_message(z_messages msg, Result result) throws Exception {
		WebSocketSession toUserWebSocketSession = z.socket_session_users.get(msg.getTouserid());
		if(z.isNotNull(toUserWebSocketSession) && toUserWebSocketSession.isOpen()) {
			String resultMessage = JsonUtil.getJson(result);
			toUserWebSocketSession.sendMessage(new TextMessage(resultMessage.getBytes()));
		}
	}

	private static void SendMessage_group_message(z_messages msg, Result result) {
	}

	private static void SendMessage_system_message(z_messages msg, Result result) {
	}

	/**
	 * 用户下线
	 * @param msg
	 * @param result 
	 * @return
	 * @throws Exception 
	 */
	private static void SendMessage_user_off_line(z_messages msg, Result result) throws Exception {
		if(z.isNotNull(msg.getFromuserid())) {
			//通知当前在线用户
			for (String key : z.socket_session_users.keySet()) {
				try {
					if(!msg.getFromuserid().equals(key)) {
						WebSocketSession userWebSocketSession = z.socket_session_users.get(key);
						if(userWebSocketSession.isOpen()) {
							String resultMessage = JsonUtil.getJson(result);
							userWebSocketSession.sendMessage(new TextMessage(resultMessage.getBytes()));
						}
					}
				} catch (IOException e) {
					z.Error("即时通讯错误|用户下线信息发送出错", e);
				}
			}
			result.setCode(Code.SUCCESS);
			result.setMsg("通知完成");
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("即时通讯错误|用户上线通知中未找到发送人ID");
		}
	}

	/**
	 * 用户上线
	 * @param msg
	 * @param result2 
	 * @return
	 * @throws Exception 
	 * @throws IOException 
	 */
	private static void SendMessage_user_on_line(z_messages msg, Result result) throws Exception {
		if(z.isNotNull(msg.getFromuserid())) {
			//通知当前在线用户
			for (String key : z.socket_session_users.keySet()) {
				try {
					if(!msg.getFromuserid().equals(key)) {
						WebSocketSession userWebSocketSession = z.socket_session_users.get(key);
						if(userWebSocketSession.isOpen()) {
							String resultMessage = JsonUtil.getJson(result);
							userWebSocketSession.sendMessage(new TextMessage(resultMessage.getBytes()));
						}
					}

				} catch (IOException e) {
					z.Error("即时通讯错误|用户上线信息发送出错", e);
				}
			}
			result.setCode(Code.SUCCESS);
			result.setMsg("通知完成");
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("即时通讯错误|用户上线通知中未找到发送人ID");
		}
	}

	/**
	 * 用户间通信
	 * @param msg
	 * @param result 
	 * @return
	 * @throws Exception 
	 */
	private static void SendMessage_usertouser(z_messages msg, Result result) throws Exception {
		if(z.isNotNull(msg.getMsg())) {
			if(z.isNotNull(msg.getTouserid())) {
				WebSocketSession toUserWebSocketSession = z.socket_session_users.get(msg.getTouserid());
				if(z.isNotNull(toUserWebSocketSession) && toUserWebSocketSession.isOpen()) {
					//当前用户在线，
					try {
						//发送消息
						String resultMessage = JsonUtil.getJson(result);
						toUserWebSocketSession.sendMessage(new TextMessage(resultMessage.getBytes()));

						//保存消息
						msg.setIs_receiving("1");//是否接收
						msg.setIs_open("0");//是否查看
						msg.setReceivingtime(DateUtil.getDateTime());//接收时间
						z.getSqlSession().insert("z_messages_insert", msg);

						//设置返回信息
						result.setCode(Code.SUCCESS);
						result.setMsg("发送成功");
					} catch (Exception e) {
						result.setCode(Code.ERROR);
						result.setMsg("即时通讯错误|信息发送出错");
						result.setData(e);
						z.Error("即时通讯错误|信息发送出错", e);
					}
				}else {
					//当前用户未登录，发送离线信息

					//保存消息
					msg.setIs_receiving("0");//是否接收
					msg.setIs_open("0");//是否查看
					z.getSqlSession().insert("z_messages_insert", msg);

					result.setCode(Code.SUCCESS);
					result.setMsg("发送成功");
				}
			}else {
				result.setCode(Code.ERROR);
				result.setMsg("即时通讯错误|接收用户不能为空");
			}
		}else {
			result.setCode(Code.ERROR);
			result.setMsg("即时通讯错误|消息为空");
		}
	}

	/**
	 * 链接建立
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception{
		String userId = GetSessionUserId(session);
		if(z.isNotNull(userId) && z.isNotNull(z.users.get(userId))) {
			z.socket_session_users.put(userId, session);
			z_user user = z.users.get(userId);
			z.session_users.put(user.getZid(), user);

			//保存用户信息到数据库
			SaveUserSessionToDB(user,session);

			//发送离线消息
			z_messages parameter = new z_messages();
			parameter.setTouserid(user.getZid());
			parameter.setIs_receiving("0");
			List<z_messages> messageList = z.getSqlSession().selectList("z_messages_select", parameter);
			for (z_messages zm : messageList) {
				if(session.isOpen()) {
					Result result = new Result();
					result.setCode(Code.SUCCESS);
					result.setMsg("离线消息");
					result.setData(zm);
					String resultMessage = JsonUtil.getJson(result);
					session.sendMessage(new TextMessage(resultMessage.getBytes()));

					//更新是否接收状态
					z_messages update_is_receiving = new z_messages();
					update_is_receiving.setZid(zm.getZid());
					update_is_receiving.setIs_receiving("1");
					update_is_receiving.setReceivingtime(DateUtil.getDateTime());
					z.getSqlSession().update("z_messages_update_zid",update_is_receiving);
				}
			}


			//z.Log("用户登录："+user.getUser_name()+" | 当前在线人数："+z.socket_session_users.size()+" 人");
		}
	} 

	/**
	 * 保存用户信息到数据库
	 * @param user
	 * @param session
	 */
	private void SaveUserSessionToDB(z_user user,WebSocketSession session) {
		//判读登陆用户是否在其它电脑登陆，如果登陆，删除其它登陆电脑状态
		String isOnlineSql = "SELECT COUNT(*) FROM z_user_online WHERE userid = '"+user.getZid()+"'"; 
		int isOnline = z.getSqlSession().selectOne("selectoneint", isOnlineSql);
		if(isOnline>0) {
			//删除其它电脑登陆状态
			String sql = "DELETE FROM z_user_online WHERE userid = '"+user.getZid()+"'";
			z.getSqlSession().delete("delete", sql);
		}
		//插入在线用户表中
		String sessionid = session.getId();
		String sql = "INSERT INTO z_user_online(zid,sid,sessionid,userid)VALUES ('"+z.newZid("z_user_online")+"','"+z.sp.get("sid")+"','"+sessionid+"','"+user.getZid()+"')";
		z.getSqlSession().insert("insert", sql);
	}

	/**
	 * 链接关闭
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session,CloseStatus status) throws Exception{ 
		String userId = GetSessionUserId(session);
		if(z.isNotNull(userId)) {
			z.socket_session_users.remove(userId);

			//删除用户session表信息
			String sql = "DELETE FROM z_user_online WHERE userid = '"+userId+"'";
			z.getSqlSession().delete("delete", sql);

			//z.Log("用户退出："+z.users.get(userId).getUser_name()+" | 当前在线人数："+z.socket_session_users.size()+" 人");
		}
	}

	private String GetSessionUserId(WebSocketSession session) {
		String userId = "";
		if(session!=null) {
			Map<String, Object> attributes = session.getAttributes();
			Object userObj = attributes.get("zuser");
			if(userObj!=null && userObj instanceof z_user) {
				z_user user = (z_user) userObj;
				userId = user.getZid();
			}
		}
		return userId;
	}

	/**
	 * 根据TextMessage转换成z_messages对象
	 * @param message
	 * @return
	 */
	private z_messages TextMessageToZMessage(TextMessage message) {
		z_messages msg = null;
		if(z.isNotNull(message.getPayload())) {
			String msgjson = message.getPayload();
			msg = JsonUtil.getObject(msgjson, z_messages.class);

			//设置Zid
			msg.setZid(z.newZid("z_messages"));

			//设置发送时间
			msg.setSendtime(DateUtil.getDateTime());

			//获取发送人与接收人名称
			if(z.isNotNull(msg.getFromuserid())) {
				z_user fromuser = z.users.get(msg.getFromuserid());
				if(z.isNotNull(fromuser)) {
					String encode_fromuser_name = "";
					try {
						//转码，前台接收到用户名称在解码
						encode_fromuser_name = URLEncoder.encode(fromuser.getUser_name(), "UTF-8")
								.replaceAll("\\+", "%20")
								.replaceAll("\\%21", "!")
								.replaceAll("\\%27", "'")
								.replaceAll("\\%28", "(")
								.replaceAll("\\%29", ")");
					} catch (UnsupportedEncodingException e) {
						z.Log("TextMessageToZMessage:获取encode_fromuser_name出错");
					}
					msg.setFromusername(encode_fromuser_name);
				}
			}
			if(z.isNotNull(msg.getTouserid())) {
				z_user touser = z.users.get(msg.getTouserid());
				if(z.isNotNull(touser)) {
					String encode_touser_name = "";
					try {
						//转码，前台接收到用户名称在解码
						encode_touser_name = URLEncoder.encode(touser.getUser_name(), "UTF-8")
								.replaceAll("\\+", "%20")
								.replaceAll("\\%21", "!")
								.replaceAll("\\%27", "'")
								.replaceAll("\\%28", "(")
								.replaceAll("\\%29", ")");
					} catch (UnsupportedEncodingException e) {
						z.Log("TextMessageToZMessage:获取encode_fromuser_name出错");
					}
					msg.setTousername(encode_touser_name);
				}
			}

		}
		return msg;
	}
}
